#ifndef _WIN32

#include "Engine.h"
#include "X11Window.h"
#include <cstring>
#include <cstdio>
#include <iostream>

/*
enum Enum
{
	MYENUM_VALUE1 = 10,
	MYENUM_VALUE2,
	MYENUM_VALUE3,
	MYENUM_VALUE4
};

int Enum2GL[]
            =
{
		GL_TEXTURE_1D, // MYENUM_VALUE1 = 0,
		GL_TEXTURE_2D,
		GL_TEXTURE_3D,
		GL_TEXTURE_CUBE_MAP_EXT,
};

Enum2GL[MYENUM_VALUE1];
*/
// --------------------------------------------------------------------------------------
// Attributes for 24-bit single buffered window
static int attrListSgl24bit[] = { GLX_RGBA,
				  GLX_RED_SIZE  ,  8,
			    	  GLX_GREEN_SIZE,  8,
			    	  GLX_BLUE_SIZE ,  8,
			    	  GLX_DEPTH_SIZE, 24,
			    	  GLX_STENCIL_SIZE, 8,
			    	  None };
// --------------------------------------------------------------------
// Attributes for 24-bit double buffered window
static int attrListDbl24bit[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
				  GLX_RED_SIZE,    8,
				  GLX_GREEN_SIZE,  8,
				  GLX_BLUE_SIZE,   8,
				  GLX_DEPTH_SIZE, 24,
				  GLX_STENCIL_SIZE, 8,
				  None };
// --------------------------------------------------------------------------------------
X11Window::X11Window( const WindowSettings& settings )
	: WindowInterface( settings),
	  dpy(NULL),
	  win(),
	  ctx(),
	  attr(),
	  screen(0),
	  running(false),
	  reverseKeyMap()
{
	memset( &attr, 0, sizeof(attr) );

	// mapeamento de teclas
	reverseKeyMap[ 32 ] = WindowInterface::KEYBOARD_SPACE;
	reverseKeyMap[ 65361 ] = WindowInterface::KEYBOARD_LEFT;
	reverseKeyMap[ 65362 ] = WindowInterface::KEYBOARD_UP;
	reverseKeyMap[ 65363 ] = WindowInterface::KEYBOARD_RIGHT;
	reverseKeyMap[ 65364 ] = WindowInterface::KEYBOARD_DOWN;

	reverseKeyMap[ 97 ] = WindowInterface::KEYBOARD_LEFT;
	reverseKeyMap[ 119 ] = WindowInterface::KEYBOARD_UP;
	reverseKeyMap[ 100 ] = WindowInterface::KEYBOARD_RIGHT;
	reverseKeyMap[ 115 ] = WindowInterface::KEYBOARD_DOWN;

	reverseKeyMap[ 65293 ] = WindowInterface::KEYBOARD_ENTER;
	reverseKeyMap[ 65307 ] = WindowInterface::KEYBOARD_ESC;

	// cria a janela no linux
	XVisualInfo *vi;
	Colormap cmap;
	Atom wmDelete;

	// escolha do visual
	dpy = XOpenDisplay(0);
	screen = DefaultScreen(dpy);
	if( (vi = glXChooseVisual(dpy, screen, attrListDbl24bit )) == NULL )
		vi = glXChooseVisual(dpy, screen, attrListSgl24bit );

	// criação do contexto de renderização
	ctx = glXCreateContext(dpy, vi, 0, GL_TRUE);
	cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),vi->visual, AllocNone);
	attr.colormap = cmap;
	attr.border_pixel = 0;

	// criação e configuração da janela
	attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
					  ButtonPressMask | StructureNotifyMask;

	win = XCreateWindow(    dpy, RootWindow(dpy, vi->screen),
				0, 0, settings.width, settings.height, 0, vi->depth,
				InputOutput, vi->visual,
				CWBorderPixel | CWColormap | CWEventMask, &attr);

	/*XSelectInput( dpy, win,
FocusChangeMask | KeyPressMask | KeyReleaseMask
| PropertyChangeMask | StructureNotifyMask | KeymapStateMask);*/

	//XSelectInput( dpy, DefaultRootWindow(dpy), KeyPressMask | KeyReleaseMask );
	XGrabKeyboard( dpy, DefaultRootWindow(dpy), False, GrabModeAsync, GrabModeAsync, CurrentTime);
	wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
	XSetWMProtocols(dpy, win, &wmDelete, 1);
	XSetStandardProperties(dpy, win, settings.title.c_str(),
			settings.title.c_str(), None, NULL, 0, NULL);
	XMapRaised(dpy, win);

	int wx, wy;
	unsigned int xwidth, xheight, wbpp;
	glXMakeCurrent(dpy, win, ctx);
	::Window winDummy;
	XGetGeometry(dpy, win, &winDummy, &wx, &wy,
				 &xwidth, &xheight, &wbpp, &wbpp);


	if( glXIsDirect(dpy, ctx) )
	{
	   printf("Direct Rendering!\n" );
	}
	else
	{
	   printf("Software Rendering! Check your video driver!\n" );
	}

}
// --------------------------------------------------------------------------------------
X11Window::~X11Window(void)
{
	//
}
// --------------------------------------------------------------------------------------
void X11Window::startRendering(void)
{
	running = true;
	while(running)
	{
		Engine::getInstance().drawScene();

		// eventos
		if( !handleX11Events() ) break;
		if( isKeyDown( WindowInterface::KEYBOARD_ESC ) ) break;
	}
}
// --------------------------------------------------------------------------------------
void X11Window::swapBuffers(void)
{
	glXSwapBuffers(dpy, win);
}
// --------------------------------------------------------------------------------------
bool X11Window::handleX11Events(void)
{
	XEvent event, next_event;

	while( XPending(dpy) > 0 )
	{
		XNextEvent(dpy, &event);
		switch(event.type)
		{
		case Expose:
			if (event.xexpose.count != 0)
				break;
		break;
		case ConfigureNotify:
		if ((event.xconfigure.width !=  settings.width) ||
			(event.xconfigure.height != settings.height))
		{
			resize( event.xconfigure.width, event.xconfigure.height );
		}
		break;
		case KeyPress:
		{
			int keyCode = XLookupKeysym( &event.xkey, 0);
			if( reverseKeyMap.find( keyCode ) != reverseKeyMap.end() )
			{
				keyMap[ reverseKeyMap[keyCode] ] = true;
			}
			break;
		}
		case KeyRelease:
		{
			int keyCode = XLookupKeysym( &event.xkey, 0);
			char pressed_keys[32];
			XQueryKeymap( dpy, pressed_keys);
			bool isPressed = (pressed_keys[event.xkey.keycode >> 3] >> (event.xkey.keycode & 0x07)) & 0x01;
			if ( !isPressed  && reverseKeyMap.find( keyCode ) != reverseKeyMap.end())
			{
				// the key has physically been released
				keyMap[ reverseKeyMap[keyCode] ] = false;
			}
			std::cout << "\n";

			/*
			if( XEventsQueued( dpy, QueuedAfterReading ) )
			{
				XPeekEvent( dpy, &next_event );
						if( next_event.type == KeyPress &&
							next_event.xkey.window == event.xkey.window &&
							next_event.xkey.keycode == event.xkey.keycode &&
							next_event.xkey.time == event.xkey.time )
						{
							// Do not report anything for this event
							XFlush(dpy); // thi
							break;
						}
			}*/
			break;
		}
		case ClientMessage:
		if (*XGetAtomName(dpy, event.xclient.message_type) == *"WM_PROTOCOLS")
		{
			return false;
		}
		break;
		default:
		break;
		} // SWITCH
	} // while

	return true;
}
// --------------------------------------------------------------------------------------
#endif
